///  1.dart中所有对象都是类，都继承自Object
///  2.使用package管理源码和属性、方法的可见性，没有访问修饰符，如果某个属性、方法需要隐藏在前面添加 _
void main() {
  var person = new Person('fauks', 12, gender: "男");
  print(person);

  // 为了防止空指针，需要做判空操作
  if (person != null) {
    person.age = 12;
  }
  // 简化写法，不需要使用if判断
  person?.age = 12;

  // 某个对象的类型
  print(person.runtimeType);

  // 调用命名构造
  var oldPerson = Person.oldPerson(122);

  // 测试继承
  //var stu = Student("三年二班");
  var stu = Student.oldPerson(12);

  // 工厂构造函数,规范final修饰比var好，不可变
  final printer = Printer.withName('佳能');
  printer.printName('slx');
}

// 枚举清晰，减少错误的方法
enum AndroidBrand {
  Xiaomi,
  Vivo,
  OPPO,
}

// dart中的get、set方法默认生成，也可以手动声明
class Person {
  // 静态变量
  static var temp = "static var";

  var name;
  var age;
  var gender;
  String firstName;
  String lastName;

  // 1.传统构造方法
  /*Person(var name, var age, var gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }*/

  // 1.1 无参数构造函数
  /*Person() {
    print("Person 无参数构造");
  }*/

  // 2.简化构造方法
  Person(this.name, this.age, {this.gender});

  // 3.命名构造函数
  Person.oldPerson(int age) {
    this.age = age;
    print("person oldPerson");
  }

  // 自定义get、set方法 直接使用访问属性的方式
  String get getFullName {
    return firstName + lastName;
  }

  set setFullName(String name) {
    var split = name.split("-");
    this.firstName = split[0];
    this.lastName = split[1];
  }

  @override
  String toString() {
    return "name=$name,age=$age,gender=$gender";
  }
}

// 继承一个类构造方法会默认调用父类无名无参数构造
// 如果父类没有无名无参数构造，则需要使用: 冒号调用其他构造
class Student extends Person {
  String clazz;

  Student.oldPerson(int age) : super.oldPerson(age);
}

class Animal {
  // 4.常量构造参数，不希望类实例化之后修改其字段
  // final 类型的字段
  final String name;

  const Animal(this.name);

  static final Animal me = const Animal("水水");
}

// 工厂构造函数,可以手动返回自定义对象，使用factory关键字
// new对象只能返回当前对象，而使用工厂可以返回任意我们想返回的对象，例如map的工厂类可以返回LinkedHashMap
class Printer {
  final String name;

  static final Map<String, Printer> _cache = Map<String, Printer>();

  Printer.newPrinter(this.name);

  factory Printer.withName(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final printer = Printer.newPrinter(name);
      _cache[name] = printer;
      return printer;
    }
  }

  void printName(String content) {
    print('$name..$content');
  }

  static void readMe() {
    print('static');
  }
}
